using System;
using System.Collections.Generic;
using System.IO;
using System.Globalization;
using System.Text;
using System.Text.RegularExpressions;

namespace libntregsharp
{
	public class NodeKey : IKey
	{
		private Regex _regex;
		
		private List<IKey> _subkeys; 
		
		public NodeKey ()
		{
		}
		
		public NodeKey (int index, byte[] hive)
		{
			
			//the lengths we will be working with.
			int word = 2;
			int dword = word+word; //double word
			int qword = dword+dword; //quad word
			
			this.OffsetFromZero = index;
			Console.WriteLine("\r\nOffset from zeroth byte: " + index.ToString());
			
			ASCIIEncoding enc = new ASCIIEncoding();
			
			//Get name length
			
			//hive[index+(int)0x0048]
			
			byte[] lb = new byte[dword]; //should only be a word length. not sure why I need to make this dword
					
			for (int k = 0;k<word;k++)
				lb[k] = hive[index+(int)0x0048+k];
					
			int nameLength = BitConverter.ToInt32(lb, 0);
			int keyLength = 128+nameLength;
			byte[] bs = new byte[keyLength];
			
			for (int k = 0; k < keyLength;k++)
			{
				bs[k] = hive[index+k];
			}
			
			if ((int)bs[0] == 110)
			{
				if ((int)bs[1] != 107) 
					throw new Exception("Not a node key.");
			}
			else
				throw new Exception("Not a node key.");
			
			for (int i = 2; i < bs.Length;)
			{
				
				if (i == (int)0x0002)
				{
					if (bs[i] != (byte)0x2C)
						//it's not a root key!
						Console.WriteLine("It's not a root key!");
					else
						//It's a root key!
						Console.WriteLine("It's a root key!");
					
					i += word; //move up 2 elements
					continue;
				}
				
				else if (i == (int)0x0004)
				{
					byte[] blah = new byte[qword];
					for (int k = 0;k<qword;k++)
						blah[k] = bs[i+k];
						
					//long t = NTUtils.SMBHexStampToUnixLong(BitConverter.ToString(blah).Replace("-",""));
					
					//DateTime date = NTUtils.ConvertFromUnixTimestamp(t);
					
					//Console.WriteLine("Date written: " + date.ToLongDateString());
					
					i+= qword;
				}
				else if (i == (int)0x0010)  //offset to parent
				{
					byte[] offsetBytes = new byte[dword];
					
					for (int k = 0;k<dword;k++)
						offsetBytes[k] = bs[i+k];
					
					int offset = BitConverter.ToInt32(offsetBytes, 0);
					
					Console.WriteLine(String.Format("Offset to Parent: {0}", offset));
					
					i += dword;
				}

				else if (i == (int)0x0014) //number of sub keys
				{
					byte[] subkeyBytes = new byte[dword];
					
					for (int k = 0;k<dword;k++)
						subkeyBytes[k] = bs[i+k];
					
					int subkeys = BitConverter.ToInt32(subkeyBytes, 0);
					
					Console.WriteLine(String.Format("Number of Subkeys: {0}", subkeys));
					
					i += dword;
				}
				else if (i == (int)0x001C) //offset to subkey lf blocks
				{					
					byte[] subkeyBytes = new byte[dword];
					
					for (int k = 0;k<dword;k++)
						subkeyBytes[k] = bs[i+k];
					
					int subkeys = BitConverter.ToInt32(subkeyBytes, 0);
					
					Console.WriteLine(String.Format("Offset to Subkey LF Blocks: {0}", subkeys));
					
					i += dword;
				}
				else if (i == (int)0x0024) //number of values
				{					
					byte[] valuesBytes = new byte[dword];
					
					for (int k = 0;k<dword;k++)
						valuesBytes[k] = bs[i+k];
					
					int values = BitConverter.ToInt32(valuesBytes, 0);
					
					Console.WriteLine(String.Format("Number of values: {0}", values));
					
					i += dword;
				}
				else if (i == (int)0x0028) //offset to value list
				{
					byte[] offsetBytes = new byte[dword];
					
					for (int k = 0;k<dword;k++)
						offsetBytes[k] = bs[i+k];
					
					int offset = BitConverter.ToInt32(offsetBytes, 0);
					
					Console.WriteLine(String.Format("Offset to value list: {0}", offset));
					
					i += dword;
				}
				else if (i == (int)0x002C) //offset to sk block
				{
					byte[] offsetBytes = new byte[dword];
					
					for (int k = 0;k<dword;k++)
						offsetBytes[k] = bs[i+k];
					
					int offset = BitConverter.ToInt32(offsetBytes, 0);
					
					Console.WriteLine(String.Format("Offset to security key: {0}", offset));
					
					i += dword;
				}
				else if (i == (int)0x0030) //offset to classname
				{
					byte[] offsetBytes = new byte[dword];
					
					for (int k = 0;k<dword;k++)
						try{
							offsetBytes[k] = bs[i+k];
						}
						catch (Exception ex)
						{
							break;
						}
					
					int offset = BitConverter.ToInt32(offsetBytes, 0);
					
					Console.WriteLine(String.Format("Offset to classname: {0}", offset));
					
					i += dword;
				}
				else if (i == (int)0x0044) //trash
				{	
					i += dword;
				}
				else if (i == (int)0x0048) //name length
				{
					i += word;
				}
				else if (i == (int)0x004A) //classname length
				{
					byte[] lengthBytes = new byte[dword];
					
					for (int k = 0;k<word;k++)
						lengthBytes[k] = bs[i+k];
					
					int length = BitConverter.ToInt32(lengthBytes, 0);
					
					Console.WriteLine(String.Format("Classname Length: {0}", length));
					
					i += word;
				}
				else if (i == (int)0x004C) //key name
				{
					int length = nameLength;
					
					if (length > bs.Length)
						length = length - (length - bs.Length);
					
					char[] blah = new char[length];
					
					for (int k = 0; k < length;k++)
						blah[k] = (char)bs[i+k]; 
					
					Console.WriteLine("Name: " + (this.KeyName = new string(blah)));
					
					i += bs.Length - i; //we are done.
				}
				else 
					i+= word;
			}
		}
		
		public int OffsetFromZero {get; set;}
		
		public Regex Regex 
		{
			get
			{
				if (_regex == null)
					_regex = new Regex(@"nk[\x2c|\x20]\x00.{7}\x01");
				
				return _regex;
			}
		}
		
		public string KeyName { get; private set; }
		
		public List<IKey> Subkeys 
		{ 
			get
			{
				if (_subkeys == null)
					_subkeys = new List<IKey>();
				
				return _subkeys;
			}
			private set
			{
				_subkeys = value;
			}
		}
		
		
		
	}
}

